package com.imddy.tweb.util;

import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HttpClientUtils0 {

	private static Log log = LogFactory.getLog(HttpClientUtils0.class);
	
	private static int socketTimeout = 15000;
	private static int connectTimeout = 15000;
	private static int connectionRequestTimeout = 15000;
	private static RequestConfig requestConfig = null;

	private static int connMgrMaxTotal = 100;
	private static int connMgrMaxPerRoute = 100;
	private static PoolingHttpClientConnectionManager connMgr = null;
	
	static {
		requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectionRequestTimeout).build();
		connMgr = new PoolingHttpClientConnectionManager();
		connMgr.setDefaultMaxPerRoute(connMgrMaxPerRoute);
		connMgr.setMaxTotal(connMgrMaxTotal);
	}

	
	
	private HttpClientUtils0() {
	}

	private static String doHttpGet(HttpGet httpGet) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			httpClient = HttpClients.createDefault();
			//httpClient = HttpClients.custom().setConnectionManager(connMgr).build();
			httpGet.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpGet);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					EntityUtils.consume(response.getEntity());
					response.close();
				}
				if (httpClient != null) {
					httpClient.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;

	}
	
	private static String doHttpPost(HttpPost httpPost) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;

		try {
			// 创建默认的httpClient实例.
			httpClient = HttpClients.createDefault();
			// httpClient = HttpClients.custom().setConnectionManager(connMgr).build();
			httpPost.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpPost);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					EntityUtils.consume(response.getEntity());
					response.close();
				}
				if (httpClient != null) {
					httpClient.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;

	}
	
	
	/**
	 * 发送Get请求Https
	 * 
	 * @param httpGet
	 * @return
	 */
	@SuppressWarnings("unused")
	private static String doHttpsGet(HttpGet httpGet) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
			DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
			// httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).setConnectionManager(connMgr).build();
			httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
			httpGet.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpGet);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					EntityUtils.consume(response.getEntity());
					response.close();
				}
				if (httpClient != null) {
					httpClient.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}

	/**
	 * 发送Post请求Https
	 * @param httpPosts
	 * @return
	 */
	@SuppressWarnings("unused")
	private static String doHttpsPost(HttpPost httpPost) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpPost.getURI().toString()));
			DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
			// httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).setConnectionManager(connMgr).build();
			httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
			httpPost.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpPost);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					EntityUtils.consume(response.getEntity());
					response.close();
				}
				if (httpClient != null) {
					httpClient.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}
	
	
	
	
	
	// 通用的http和https都可以使用, 这个房返回的一个HttpResponse ,所以相关的链接是没有关闭的。谨慎使用，只能用于测试。
	@SuppressWarnings("unused")
	private static CloseableHttpResponse doHttpIt(HttpRequestBase httpRequestBase) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		try {
			// 创建默认的httpClient实例.
			String scheme = httpRequestBase.getURI().getScheme();
			if (scheme.equalsIgnoreCase("https")) {
				PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpRequestBase.getURI().toString()));
				DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
				// httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).setConnectionManager(connMgr).build();
				httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
			} else if (scheme.equalsIgnoreCase("http")) {
				// httpClient = HttpClients.custom().setConnectionManager(connMgr).build();
				httpClient = HttpClients.createDefault();
			} else {
				throw new IllegalArgumentException("url的scheme错误，必须是http或者https！ ");
			}
			httpRequestBase.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpRequestBase);
			
			return response;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
//			try {
//				// 关闭连接,释放资源
//				if (response != null) {
//					EntityUtils.consume(response.getEntity());
//					response.close();
//				}
//				if (httpClient != null) {
//					httpClient.close();
//				}
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
		}
		return response;
	}
	
	
	// 通用的http和https都可以使用。
	@SuppressWarnings("unused")
	private static String doHttpIt2(HttpRequestBase httpRequestBase) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			String scheme = httpRequestBase.getURI().getScheme();
			if (scheme.equalsIgnoreCase("https")) {
				PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpRequestBase.getURI().toString()));
				DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
				// httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).setConnectionManager(connMgr).build();
				httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
			} else if (scheme.equalsIgnoreCase("http")) {
				httpClient = HttpClients.createDefault();
			} else {
				throw new IllegalArgumentException("url的scheme错误，必须是http或者https .");
			}
			httpRequestBase.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpRequestBase);
			responseContent = EntityUtils.toString(response.getEntity(), "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					EntityUtils.consume(response.getEntity());
					response.close();
				}
				// 这里不能关闭httpClient， 这个会关连接池
				//if (httpClient != null) {
				//	httpClient.close();
				//}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}
	
	// it3是自定的HTTPS实现。
	@SuppressWarnings("unused")
	private static String doHttpIt3(HttpRequestBase httpRequestBase) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			String scheme = httpRequestBase.getURI().getScheme();
			if (scheme.equalsIgnoreCase("https")) {
				httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).build();
			} else if (scheme.equalsIgnoreCase("http")) {
				httpClient = HttpClients.createDefault();
			} else {
				throw new IllegalArgumentException("url的scheme错误，必须是http或者https .");
			}
			httpRequestBase.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpRequestBase);
			responseContent = EntityUtils.toString(response.getEntity(), "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					EntityUtils.consume(response.getEntity());
					response.close();
				}
				// 这里不能关闭httpClient， 这个会关连接池
				//if (httpClient != null) {
				//	httpClient.close();
				//}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}
	
	// it4是自定的HTTPS实现。
	@SuppressWarnings("unused")
	private static String doHttpIt4(HttpRequestBase httpRequestBase) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			String scheme = httpRequestBase.getURI().getScheme();
			if (scheme.equalsIgnoreCase("https")) {
				httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory2()).build();
			} else if (scheme.equalsIgnoreCase("http")) {
				httpClient = HttpClients.createDefault();
			} else {
				throw new IllegalArgumentException("url的scheme错误，必须是http或者https .");
			}
			httpRequestBase.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpRequestBase);
			responseContent = EntityUtils.toString(response.getEntity(), "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					EntityUtils.consume(response.getEntity());
					response.close();
				}
				// 这里不能关闭httpClient， 这个会关连接池
				//if (httpClient != null) {
				//	httpClient.close();
				//}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return responseContent;
	}
	
	/**
	 *  sendHttpGet(url)
	 * @param url
	 * @return
	 */
	public static String sendHttpGet(String url) {
		return doHttpGet(new HttpGet(url));
	}
	
	/**
	 * sendHttpGet()
	 * @param url
	 * @param param key1=value1&key2=value2&key3=value3
	 * @return
	 */
	public static String sendHttpGet(String url, String param) {
		// 创建httpGet
		HttpGet httpGet = new HttpGet(url + '?' + param);
		
		return doHttpGet(httpGet);
	}
	
	/**
	 * sendHttpPost()
	 * @param url
	 * @param param key1=value1&key2=value2&key3=value3
	 * @return
	 */
	public static String sendHttpPost(String url, String param) {
		// 创建httpPost
		HttpPost httpPost = new HttpPost(url);
		try {
			StringEntity stringEntity = new StringEntity(param, "UTF-8");
			stringEntity.setContentType("application/x-www-form-urlencoded");
			httpPost.setEntity(stringEntity);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return doHttpPost(httpPost);
	}
	
	/**
	 * sendHttpGet
	 * @param url
	 * @param param 是个map<String, String>
	 * @return
	 */
	public static String sendHttpGet(String url, Map<String, String> param) {
		// 创建httpGet
		String paramStr = "";
		for (String key : param.keySet()) {
			String tmp = "";
			tmp = key + "=" + param.get(key);
			paramStr += tmp;
		}
		HttpGet httpGet = new HttpGet(url + '?' + paramStr);
		
        return doHttpGet(httpGet);
	}
	
	public static String sendHttpPost(String url, Map<String, String> param) {
		// 创建httpPost
		HttpPost httpPost = new HttpPost(url);
		// 创建参数队列 
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : param.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, param.get(key)));   
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));    
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return doHttpPost(httpPost);
	}
	
	public static String sendHttpPostJson(String url, String json) {
		// 创建httpPost
		HttpPost httpPost = new HttpPost(url);
		try {
			// StringEntity stringEntity = new StringEntity(param, "UTF-8");
			// stringEntity.setContentType("application/json");
			// stringEntity.setContentEncoding("UTF-8");
			// stringEntity.setContentType("application/json");
			StringEntity stringEntity = new StringEntity(json, ContentType.create("application/json", "UTF-8"));
			httpPost.setEntity(stringEntity);
		} catch (Exception e) {
			e.printStackTrace();
		}
						
		return doHttpPost(httpPost);
	}
	
	
	// 创建SSL安全连接,用余创建https的httpclients
	@SuppressWarnings({ "deprecation" })
	private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
		SSLConnectionSocketFactory sslsf = null;
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					return true;
				}
			}).build();
			sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {

				@Override
				public boolean verify(String arg0, SSLSession arg1) {
					return true;
				}

				@Override
				public void verify(String host, SSLSocket ssl) throws IOException {
				}

				@Override
				public void verify(String host, X509Certificate cert) throws SSLException {
				}

				@Override
				public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
				}
			});
		} catch (GeneralSecurityException e) {
			e.printStackTrace();
		}
		return sslsf;
	}
	
	// 创建SSL安全连接,用余创建https的httpclients
		@SuppressWarnings({ "deprecation" })
		private static SSLConnectionSocketFactory createSSLConnSocketFactory2() {
			SSLConnectionSocketFactory sslsf = null;
		X509TrustManager x509mgr = new X509TrustManager() {
			@Override
			public void checkClientTrusted(X509Certificate[] xcs, String string) {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] xcs, String string) {
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};
		try {
			SSLContext sslContext = SSLContext.getInstance("TLS");
			sslContext.init(null, new TrustManager[] { x509mgr }, new java.security.SecureRandom());
			sslsf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sslsf;
	}
	
	/**
	 * main测试
	 * 
	 * @param args
	 * @throws Exception 
	 * @throws  
	 */
	public static void main(String[] args) throws Exception {
		
		String url = "http://api.crpay.com/payapi/gateway";
		String param = "merchant_no=TOF00001&method=unified.trade.pay&version=1.0";
		Map map = new HashMap<String, String>();
		map.put("merchant_no", "TOF00001");
		map.put("method", "unified.trade.pay");
		map.put("version", "1.0");
		
		
		// 由于全部没有走连接池，所有直接跑所有测试没有问题  ，并且关闭httpClient，关闭连接池的地方都注销了
		
		System.out.println(HttpClientUtils0.sendHttpPost(url, map));
		System.out.println(HttpClientUtils0.sendHttpPost(url, param));
		
		System.out.println(HttpClientUtils0.doHttpsGet(new HttpGet("https://www.baidu.com")));
		System.out.println(HttpClientUtils0.doHttpsPost(new HttpPost("https://www.baidu.com")));
		
		System.out.println(EntityUtils.toString( HttpClientUtils0.doHttpIt(new HttpPost("https://www.baidu.com/")).getEntity(), "UTF-8") );
		System.out.println(HttpClientUtils0.doHttpIt2(new HttpGet("http://www.baidu.com/s?wd=aaa")));
		System.out.println(HttpClientUtils0.doHttpIt3(new HttpGet("http://www.baidu.com/s?wd=aaa")));
		
		Map map2 = new HashMap<String, String>();
		map2.put("wd", "aaa");
		System.out.println(HttpClientUtils0.sendHttpGet("http://www.baidu.com/s",map2));
		
		System.out.println(HttpClientUtils0.doHttpIt2(new HttpGet("http://www.baidu.com/s?wd=aaa")));
		System.out.println(HttpClientUtils0.doHttpIt3(new HttpGet("https://www.baidu.com/")));
		System.out.println(HttpClientUtils0.doHttpIt4(new HttpGet("https://www.baidu.com/")));
		System.out.println(HttpClientUtils0.sendHttpGet("https://www.cnblogs.com/hugo-zhangzhen/p/6858013.html"));
		System.out.println(HttpClientUtils0.sendHttpGet("https://www.cnblogs.com/hugo-zhangzhen/p/6739658.html"));


	}

}
